package main;


import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;

import plug.ColorCube;
import plug.CreaturePluginFactory;
import plug.creatures.PluginMenuItemBuilder;
import visual.ChoiceFrame;
import visual.StatisticTable;
import creatures.ICreature;
import creatures.visual.CreatureInspector;
import creatures.visual.CreatureSimulator;
import creatures.visual.CreatureVisualizer;

/**
 * Just a simple test of the simulator.
 * 
 */
@SuppressWarnings("serial")
public class Launcher extends JFrame {
	
	private final CreaturePluginFactory creatureFactory;
	
	private final CreatureInspector inspector;
	private final CreatureVisualizer visualizer;
	private final CreatureSimulator simulator;
	
	private PluginMenuItemBuilder menuBuilderCreature;
	private PluginMenuItemBuilder menuAddUnique;
	private PluginMenuItemBuilder menuStat;
	
	private JMenuBar mb = new JMenuBar();		
	private Collection<String> pluginsNames;
	private ArrayList<String> pluginsSelected = new ArrayList<String>();
	private String pluginAddUniqueName;
	private String statName;
	  
	public Launcher()  {
		pluginsNames = new ArrayList<String>();
		creatureFactory = CreaturePluginFactory.getInsance();
		
		setName("Creature Simulator Plugin Version");
		setLayout(new BorderLayout());
		
		JPanel buttons = new JPanel();
		JButton loader = new JButton("Load plugins");
		loader.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				creatureFactory.load();
				buildPluginMenus();
			}
		});
		buttons.add(loader);


		JButton restart = new JButton("(Re-)start simulation");
		restart.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(pluginsNames.size()>0) {
					synchronized(simulator) {
						if (simulator.isRunning()) {
							simulator.stop();
						}
					}
					simulator.clearCreatures();
					new ChoiceFrame(Launcher.this, simulator, pluginsNames).setVisible(true);
					simulator.start();
					if (simulator.getStatTable() != null) {
						if (simulator.getStatTable().isVisible()) {
							simulator.getStatTable().setVisible(false);
							simulator.setStatisticTable(new StatisticTable((ArrayList<? extends ICreature>) simulator.getCreatures(), pluginsSelected));
							simulator.showStatTable();
						}
						else {	
							simulator.setStatisticTable(new StatisticTable((ArrayList<? extends ICreature>) simulator.getCreatures(), pluginsSelected));
						}
					}
					else {	
						simulator.setStatisticTable(new StatisticTable((ArrayList<? extends ICreature>) simulator.getCreatures(), pluginsSelected));
					}
				}
			}
		});
		
		buttons.add(restart);
		
		JButton stat = new JButton("Show statistics");
		stat.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(statName!=null) {
					switch(simulator.getStatMap().get(statName)) {
						case 0:
							if (simulator.getStatTable() == null) {
								simulator.setStatisticTable(new StatisticTable((ArrayList<? extends ICreature>) simulator.getCreatures(), pluginsSelected));
							}
							else {
								if (simulator.getStatTable().isVisible()) {
									simulator.getStatTable().setVisible(false);
								}
							}
							simulator.showStatTable(); 
							break;
						default: 
							System.err.println("INFO: statistics view unknown.");
					}
				}
			}
		});
		
		buttons.add(stat);
		
		add(buttons, BorderLayout.SOUTH);
				
		simulator = new CreatureSimulator(new Dimension(640, 480));
		inspector = new CreatureInspector();
		inspector.setFocusableWindowState(false);
		visualizer = new CreatureVisualizer(simulator,this);
		visualizer.setDebug(false);
		visualizer.setPreferredSize(simulator.getSize());
				
		add(visualizer, BorderLayout.CENTER);
	
	    buildPluginMenus();

	    pack();

		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent evt) {
				exit(evt);
			}
		});						
	}
	
	
	private void exit(WindowEvent evt) {
		System.exit(0);
	}

	public void buildPluginMenus() {	
		mb.removeAll();
		ActionListener listener = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				// the name of the plugin is in the ActionCommand
				JCheckBoxMenuItem source = (JCheckBoxMenuItem) e.getSource();
				
				if(source.isSelected())
					pluginsNames.add(source.getActionCommand());
				else {
					pluginsNames.remove(source.getActionCommand());
					pluginsSelected.remove(source.getActionCommand());
				}
				for (String pluginsName : pluginsNames) {
					if (!pluginsSelected.contains(pluginsName)) {
						pluginsSelected.add(pluginsName);
					}
				}
				if (simulator.getStatTable() != null) {
					if (simulator.getStatTable().isVisible()) {
						simulator.getStatTable().setVisible(false);
						simulator.setStatisticTable(new StatisticTable((ArrayList<? extends ICreature>) simulator.getCreatures(), pluginsSelected));
						simulator.showStatTable();
					}
					else {	
						simulator.setStatisticTable(new StatisticTable((ArrayList<? extends ICreature>) simulator.getCreatures(), pluginsSelected));
					}
				}
				else {	
					simulator.setStatisticTable(new StatisticTable((ArrayList<? extends ICreature>) simulator.getCreatures(), pluginsSelected));
				}
			}
		};
		menuBuilderCreature = new PluginMenuItemBuilder(creatureFactory.getConstructorMap(),listener);
		menuBuilderCreature.setMenuTitle("Plugins");
		menuBuilderCreature.buildMenuWithCheckBox();
		mb.add(menuBuilderCreature.getMenu());
		
		ActionListener listenerAddUnique = new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				pluginAddUniqueName = e.getActionCommand();
				if (!pluginsSelected.contains(pluginAddUniqueName)) {
					pluginsSelected.add(pluginAddUniqueName);
				}
				if (simulator.getStatTable() != null) {
					if (simulator.getStatTable().isVisible()) {
						simulator.getStatTable().setVisible(false);
						simulator.setStatisticTable(new StatisticTable((ArrayList<? extends ICreature>) simulator.getCreatures(), pluginsSelected));
						simulator.showStatTable();
					}
					else {	
						simulator.setStatisticTable(new StatisticTable((ArrayList<? extends ICreature>) simulator.getCreatures(), pluginsSelected));
					}
				}
				else {	
					simulator.setStatisticTable(new StatisticTable((ArrayList<? extends ICreature>) simulator.getCreatures(), pluginsSelected));
				}
			}
		};
		
		menuAddUnique = new PluginMenuItemBuilder(creatureFactory.getConstructorMap(), listenerAddUnique);
		menuAddUnique.setMenuTitle("Add (One)");
		menuAddUnique.builMenuWithCheckBoxGroup();
		mb.add(menuAddUnique.getMenu());
		
		ActionListener listenerShowStatistics = new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				statName = e.getActionCommand();
			}
		};
		
		
		menuStat = new PluginMenuItemBuilder(listenerShowStatistics, simulator.getStatMap());
		menuStat.setMenuTitle("Statistics");
		menuStat.buildStatMenuWithCheckBox();
		mb.add(menuStat.getMenu());
			
		setJMenuBar(mb);
					
	}
	
	
	public static void main(String args[]){
	    Logger.getLogger("plug").setLevel(Level.INFO);
		double myMaxSpeed = 5;
		CreaturePluginFactory.init(myMaxSpeed);
		Launcher launcher = new Launcher();
		launcher.setVisible(true);
	}


	public void createUniqueCreature(int x, int y) {
		if(pluginAddUniqueName!=null) {
			
			synchronized(simulator) {
				if (simulator.isRunning()) {
					simulator.stop();
				}
			}
			simulator.addAllCreatures(creatureFactory.createOneCreature(simulator,new ColorCube(50), pluginAddUniqueName, x, y));
			simulator.start();
		}
	}
	
}


